#include "BoxMesh.h"
#include "../View/RenderContext.h"
#include "../Core/glExt.h"
#include "../Core/Point2.h"
#include "../Core/Color4.h"
#include <algorithm>
#include "../Core/GlPlatform.h"

namespace Model {
	namespace { // Box data
		using namespace Core;

		static const float h = 0.5f;
		static const Point3f vertices[] = {
			Point3f( -h, -h, -h ),
			Point3f(  h, -h, -h ),
			Point3f(  h, -h,  h ),
			Point3f( -h, -h,  h ),
			Point3f( -h,  h, -h ),
			Point3f(  h,  h, -h ),
			Point3f(  h,  h,  h ),
			Point3f( -h,  h,  h )
		};
		static const unsigned faces[6][4] = {
			{ 0, 1, 5, 4 },
			{ 1, 2, 6, 5 },
			{ 2, 3, 7, 6 },
			{ 3, 0, 4, 7 },
			{ 3, 2, 1, 0 },
			{ 4, 5, 6, 7 }
		};
		static const Core::Vector3f normals[6] = {
			Vector3f(  0,  0, -1 ),
			Vector3f(  1,  0,  0 ),
			Vector3f(  0,  0,  1 ),
			Vector3f( -1,  0,  0 ),
			Vector3f(  0, -1,  0 ),
			Vector3f(  0,  1,  0 )
		};
		static const Core::Color4 colors[6] = {
			Color4( 1, 0, 0 ),
			Color4( 1, 1, 0 ),
			Color4( 0, 1, 0 ),
			Color4( 0, 1, 1 ),
			Color4( 0, 0, 1 ),
			Color4( 1, 0, 1 )
		};
		static const unsigned edges[12][2] = {
			{ 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 }, // Bottom-face
			{ 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 4 },
			{ 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 }
		};
	}

	void BoxMesh::onRender( View::RenderContext& rx ) {
		using namespace Core;

		glPushMatrix(); {
			glExt::scale( mDimensions );

			if ( rx.wireframe ) { 
				glBegin( GL_LINES ); {
					for ( int idx = 0; idx < 12; ++idx ) {
						const unsigned (&edge)[2] = edges[idx];
						glExt::emitVertex3( vertices[edge[0]] );
						glExt::emitVertex3( vertices[edge[1]] );
					}
				} glEnd();
			} else {
				glBegin( GL_QUADS ); {
					// glExt::emitColor( colors[0] );
					for ( int f = 0; f < 6; ++f ) {
						const unsigned (&indices)[4] = faces[f];

						glExt::emitNormal( normals[f] );
						glExt::emitColor( colors[f] );
						for ( int v = 0; v < 4; ++v )
							glExt::emitVertex3( vertices[indices[v]] );
					}
				} glEnd();
			}
		} glPopMatrix();
	}
}


// Box indices:
// 
//      7------6
//     /|     /|
//    4------5 |
//    | |    | |
//    | 3----|-2
//    |/     |/    
//    0------1    
// 
